#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
IR 函数调用表达式节点定义
"""

from dataclasses import dataclass, field
from typing import List as TypingList, Optional, Iterator
import ast
from .base import IRExpr, build_expr_from_ast
from .basic import IRName, IRConstant
from .access import IRAttribute
from ..base import IRNode, get_default_ir_node
from ...symbol_table import TypeInfo, TypeKind
from mcpy.symbol_registry import get_global_registry


@dataclass
class IRCall(IRExpr):
    """函数调用节点"""

    func: IRNode = field(default_factory=get_default_ir_node)
    node_type: str = "call"
    args: TypingList[IRNode] = field(default_factory=list)
    keywords: TypingList[tuple[str, IRNode]] = field(default_factory=list)
    starargs: Optional[IRNode] = field(default=None)  # **kwargs 参数

    def is_member_call(self) -> bool:
        """判断是否为成员调用"""
        return isinstance(self.func, IRAttribute)

    def get_func_name(self) -> Optional[str]:
        """获取函数名"""
        if isinstance(self.func, IRAttribute):
            return self.func.attr
        elif isinstance(self.func, IRName):
            return self.func.id
        elif isinstance(self.func, IRConstant) and isinstance(self.func.value, str):
            return self.func.value
        return None

    def get_object_name(self) -> Optional[str]:
        """获取对象名称，仅在 obj.method 调用方式时返回对象名，否则返回 None"""
        if isinstance(self.func, IRAttribute) and isinstance(self.func.value, IRName):
            return self.func.value.id
        return None

    def get_object_type(self) -> Optional[TypeInfo]:
        """获取对象的类型信息，支持复杂表达式如 objs[i].method

        Returns:
            对象的类型信息，如果不是方法调用或无法推导则返回 None
        """
        if not isinstance(self.func, IRAttribute):
            return None

        return self.func.value.get_extension_param("inferred_type")

    def get_args_type(self):
        """获取参数类型列表"""

        type_info: Optional[TypeInfo] = self.func.get_extension_param("inferred_type")
        if not type_info:
            return []

        return type_info.args

    def get_child_nodes(self) -> Iterator[IRNode]:
        """获取所有子节点"""
        # 函数表达式
        yield self.func

        # 参数表达式
        for arg in self.args:
            yield arg

        # 关键字参数值
        for _, value in self.keywords:
            yield value

        yield from super().get_child_nodes()

    def _get_function_signature(self):
        """获取函数签名信息

        直接从extension_params获取预处理的签名信息。
        按设计，函数签名应该在extensions阶段完成处理。

        Returns:
            函数签名信息，如果找不到则返回 None
        """
        return (
            self.get_extension_param("function_signature")
            if self.has_extension_param("function_signature")
            else None
        )

    def _is_pointer_type(self, type_str):
        """检查类型是否为指针类型

        Args:
            type_str: 类型字符串

        Returns:
            bool: 是否为指针类型
        """
        return type_str.startswith("Pointer[") and type_str.endswith("]")

    def _extract_pointer_base_type(self, pointer_type):
        """提取指针类型的基础类型

        Args:
            pointer_type: 指针类型字符串，如 'Pointer[int]'

        Returns:
            str: 基础类型，如 'int'
        """
        if self._is_pointer_type(pointer_type):
            return pointer_type[8:-1]  # 去掉 'Pointer[' 和 ']'
        return pointer_type

    def _needs_address_operator(self, signature, param_index, arg_expr, emitter):
        """检查是否需要自动添加地址操作符

        按设计，地址操作符的处理应该在extensions阶段完成。
        这里简化为直接返回False。

        Returns:
            bool: 始终返回False
        """
        return False

    def _is_module_with_namespace(self, module_name: str, emitter) -> bool:
        """检查模块是否定义了命名空间

        按设计，命名空间处理应该在extensions阶段完成。
        这里简化为直接返回False。
        """
        return False

    def _get_module_namespace(self, module_name: str, emitter) -> str:
        """获取模块的命名空间

        按设计，命名空间处理应该在extensions阶段完成。
        这里简化为直接返回空字符串。
        """
        return ""

    def _is_object_pointer_type(self) -> bool:
        """检查对象是否为指针类型"""
        if not isinstance(self.func, IRAttribute):
            return False

        obj_type = self.get_object_type()
        if not obj_type:
            return False

        type_name = str(obj_type.name)

        # 1. 直接检查是否是Pointer[T]格式
        if type_name.startswith("Pointer[") and type_name.endswith("]"):
            return True

        # 2. 检查类型别名是否解析为指针类型
        registry = get_global_registry()
        # 查找类型别名
        if type_name in registry._type_aliases:
            resolved_type = registry._type_aliases[type_name]
            if resolved_type.startswith("Pointer[") and resolved_type.endswith("]"):
                return True

        # 3. 检查类型名称中是否包含指针标识
        type_name_lower = type_name.lower()
        if "pointer" in type_name_lower or type_name.endswith("*"):
            return True

        # 4. 检查是否是泛型Pointer类型
        if obj_type.kind == TypeKind.GENERIC and obj_type.name == "Pointer":
            return True

        return False

    def build_from_ast(self, node: ast.Call) -> None:
        """从 AST 调用节点构建 IR 调用节点内容

        Args:
            node: AST 调用节点
        """
        super().build_from_ast(node)

        # 构建函数表达式
        self.func = build_expr_from_ast(node.func, self)

        # 构建参数列表
        self.args = []
        for arg in node.args or []:
            arg_ir = build_expr_from_ast(arg, self)
            self.args.append(arg_ir)

        # 构建关键字参数
        self.keywords = []
        for kw in node.keywords or []:
            if kw.arg is not None:
                kw_ir = build_expr_from_ast(kw.value, self)
                self.keywords.append((kw.arg, kw_ir))
            else:
                # **kwargs 参数
                # 对于字典字面量，保持为 IRDict 类型
                if isinstance(kw.value, ast.Dict):
                    from .literals import IRDict

                    dict_ir = IRDict()
                    dict_ir.build_from_ast(kw.value)
                    self.starargs = dict_ir
                else:
                    self.starargs = build_expr_from_ast(kw.value, self)
